package borrador.grafica;

import java.io.File;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import logica.Atributo;
import logica.AtributoSimple;
import logica.AtributoSimpleException;
import logica.Entidad;
import logica.EntidadRol;
import logica.Jerarquia;
import logica.Proyecto;
import logica.Relacion;
import logica.SinNombreException;
import vista.objetos.AtributoGraficable;
import vista.objetos.AtributoGraficableCompuesto;
import vista.objetos.AtributoTipoNoSoportadoException;
import vista.objetos.DiagramaGraficable;
import vista.objetos.EntidadGraficable;
import vista.objetos.EntidadRolGraficable;
import vista.objetos.EntidadTipoNoSoportadoException;
import vista.objetos.FabricaAtributoGraficable;
import vista.objetos.FabricaAtributoGraficableCompuesto;
import vista.objetos.FabricaEntidadGraficable;
import vista.objetos.FabricaRelacionGraficable;
import vista.objetos.Graficable;
import vista.objetos.GraficableConEtiqueta;
import vista.objetos.JerarquiaGraficable;
import vista.objetos.ProyectoGraficable;
import vista.objetos.RelacionGraficable;
import vista.objetos.RelacionTipoNoSoportadoException;
import xml.XMLManager;
import controlador.ControladorCrearProyecto;
import controlador.ControladorDeTiposDeObjetos;
import controlador.CrearProyectoException;
import controlador.NoExisteEntidadGraficable;

public class TransformadorAGraficable {

	private static ControladorDeTiposDeObjetos controladorTipos = ControladorDeTiposDeObjetos.getInstancia();
	
	public static List<EntidadRolGraficable> getEntidadRolGraficables(List<EntidadRol> entidadRoles, DiagramaGraficable diagrama) throws NoExisteEntidadGraficable 
	{
		List<EntidadRolGraficable> entidadesRolesGraficables = new LinkedList<EntidadRolGraficable>();
		Iterator<EntidadRol> itEntidadRol = entidadRoles.iterator();
		
		while (itEntidadRol.hasNext())
		{
			EntidadRol entidadRol = (EntidadRol) itEntidadRol.next();
			EntidadGraficable entidadGraf = getEntidadGraficableExistente(entidadRol.getEntidad(), diagrama);
			EntidadRolGraficable entidadRolGraficable = new EntidadRolGraficable(entidadRol, entidadGraf);
			
			entidadesRolesGraficables.add(entidadRolGraficable);
		}
		
		return entidadesRolesGraficables;
	}
	
	public static EntidadGraficable getEntidadGraficableExistente(Entidad entidad, DiagramaGraficable diagrama) throws NoExisteEntidadGraficable
	{
		Iterator<GraficableConEtiqueta> itGraficable = diagrama.getGraficables().iterator();
		
		while (itGraficable.hasNext())
		{
			Graficable graficable = itGraficable.next();
			
			if (graficable.esElGraficableDe(entidad) == true)
				return (EntidadGraficable)graficable;			
		}

		throw new NoExisteEntidadGraficable("No existe en el diagrama actual una EntidadGraficable que represente a la Entidad: " + entidad.getNombre());
	}
	
	/* Dada una entidad me devuelve la entidad Graficable Correspondiente*/
	public static EntidadGraficable getEntidadGraficable(Entidad entidad) throws EntidadTipoNoSoportadoException
	{
		Iterator<FabricaEntidadGraficable> itTipoEntidad = controladorTipos.getTipoDeEntidades().iterator();
		
		while (itTipoEntidad.hasNext())
		{
			FabricaEntidadGraficable fabTemp = itTipoEntidad.next();
			
			if (entidad.getTipo() == fabTemp.getTipoDeEntidad())
				return fabTemp.crearEntidadGraficable(entidad);
		}
		
		throw new EntidadTipoNoSoportadoException("El tipo <" + entidad.getTipo() + "> no es soportado por la aplicacion.");
	}
	
	/* Dada una relación me devuelve la relación Graficable Correspondiente*/
	public static RelacionGraficable getRelacionGraficable(Relacion relacion) throws RelacionTipoNoSoportadoException
	{
		Iterator<FabricaRelacionGraficable> itTipoEntidad = controladorTipos.getTipoDeRelaciones().iterator();
		
		while (itTipoEntidad.hasNext())
		{
			FabricaRelacionGraficable fabTemp = itTipoEntidad.next();
			
			if (relacion.getTipo() == fabTemp.getTipoDeRelacion())
				return fabTemp.crearRelacionGraficable(relacion);
		}
		
		throw new RelacionTipoNoSoportadoException("El tipo <" + relacion.getTipo() + "> no es soportado por la aplicacion.");
	}

	/* Dada una jerarquia me devuel
	 */
	public static JerarquiaGraficable getJerarquiaGraficable(Jerarquia jerarquia) {
		return new JerarquiaGraficable(jerarquia);
	}

	/*
	 * A continuación, dado una lista de Atributos, me devuelve la lista de los AtributosGraficables
	 * con sus correspondientes referencias.
	 */
	public static List<AtributoGraficable> getAtributoGraficables(List<Atributo> atributosLogicos) throws AtributoTipoNoSoportadoException
	{
		List<AtributoGraficable> atriGraf = new LinkedList<AtributoGraficable>();
		List<FabricaAtributoGraficable> tiposAtributos = controladorTipos.getTipoDeAtributos();
		
		for (Atributo atributo: atributosLogicos)
			crearAtributoGraficable(atriGraf, tiposAtributos, atributo);
		
		return atriGraf;
	}

	public static void crearAtributoGraficable(List<AtributoGraficable> atriGraf, List<FabricaAtributoGraficable> tiposAtributos, Atributo atributo) throws AtributoTipoNoSoportadoException
	{	
		try {	
			atriGraf.add((AtributoGraficableCompuesto) (new FabricaAtributoGraficableCompuesto()).crearAtributoGraficable(atributo));
		}
		catch(AtributoSimpleException noEraCompuesto)
		{
			AtributoSimple esSimple = (AtributoSimple) atributo;
			atriGraf.add(crearAtributoGaficableSimple(esSimple, tiposAtributos));				
		}
	}
	
	private static AtributoGraficable crearAtributoGaficableSimple(AtributoSimple atributo, List<FabricaAtributoGraficable> tiposAtributos) throws AtributoTipoNoSoportadoException
	{
		Iterator<FabricaAtributoGraficable> itTipoAtributo = tiposAtributos.iterator();
		
		while(itTipoAtributo.hasNext())
		{
			FabricaAtributoGraficable fabrica = (FabricaAtributoGraficable) itTipoAtributo.next();
			
			if(atributo.getTipo().compareToIgnoreCase(fabrica.toString()) == 0)
				try {
					return fabrica.crearAtributoGraficable(atributo);
				} catch (AtributoSimpleException e) { //no puede pasar, sino => es atri compuesto
					e.printStackTrace();
				}
		}
		
		throw new AtributoTipoNoSoportadoException("El tipo " + atributo.getTipo() + " no es soportado por la aplicacion.");
		
	}
	
	public static List<EntidadGraficable> getListaEntidadGraficable(List<Entidad> entidadesLogicasH, DiagramaGraficable diagrama) throws NoExisteEntidadGraficable 
	{
		List<EntidadGraficable> entidadesGraficables = new LinkedList<EntidadGraficable>();
		Iterator<Entidad> itEntidad = entidadesLogicasH.iterator();
		
		while(itEntidad.hasNext())
			entidadesGraficables.add(TransformadorAGraficable.getEntidadGraficableExistente(itEntidad.next(), diagrama));

		return entidadesGraficables;
	}
	
	public static ProyectoGraficable setInformacionParaGuardar(Proyecto proyectoLogico) throws SecurityException, SinNombreException
	{
		ProyectoGraficable proyectoGraficable = null;
		
		/*para poder guardar el proyecto - sobreescribe archivos*/
		try{
		proyectoGraficable = ControladorCrearProyecto.crearProyectoNuevo("./test", proyectoLogico.getNombre());
		}
		catch(CrearProyectoException e){
			XMLManager.getInstance().setPath("./test" + File.separator +  proyectoLogico.getNombre() + File.separator + "Datos" + File.separator);
		}
		
		return proyectoGraficable;
	}
}
